﻿// Copyright (c) Inossem. All rights reserved.
// Licensed under the LGPL-3.0 license. See LICENSE file in the project root for full license information.
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace NamedPipeWrapper.IO
{
    /// <summary>
    /// Wraps a <see cref="PipeStream"/> object and reads from it.  Deserializes binary data sent by a <see cref="PipeStreamWriter{T}"/>
    /// into a .NET CLR object specified by <typeparamref name="T"/>.
    /// </summary>
    /// <typeparam name="T">Reference type to deserialize data to</typeparam>
    public class PipeStreamReaderEx<T> where T : class
    {
        private const int BUFFER_SIZE = 256;

        public PipeStream BaseStream { get; private set; }

        public bool IsConnected { get; private set; }

        public PipeStreamReaderEx(PipeStream stream)
        {
            BaseStream = stream;
            IsConnected = stream.IsConnected;
        }

        private T readObject()
        {
            string json = string.Empty;
            using (MemoryStream memoryStream = new MemoryStream())
            {
                byte[] buffer = new byte[BUFFER_SIZE];
                do
                {
                    memoryStream.Write(buffer, 0, BaseStream.Read(buffer, 0, buffer.Length));
                }
                while (!BaseStream.IsMessageComplete);

                json = Encoding.UTF8.GetString(memoryStream.ToArray());
            }

            return JsonConvert.DeserializeObject<T>(json);
        }

        public T ReadObject()
        {
            return readObject();
        }

        private async Task<T> readObjectAsync()
        {
            string json = string.Empty;
            using (MemoryStream memoryStream = new MemoryStream())
            {
                byte[] buffer = new byte[BUFFER_SIZE];
                do
                {
                    await memoryStream.WriteAsync(buffer, 0, await BaseStream.ReadAsync(buffer, 0, buffer.Length));
                }
                while (!BaseStream.IsMessageComplete);

                json = Encoding.UTF8.GetString(memoryStream.ToArray());
            }

            return JsonConvert.DeserializeObject<T>(json);
        }

        public async Task<T> ReadObjectAsync()
        {
            return await readObjectAsync();
        }
    }
}
